﻿/**
 * 初始化 jqGrid
 * @param {Object} config 用户自定义配置，会与默认配置进行合并
 */
function initializeJqGrid(config = {}) {
    // 默认配置（涵盖常见属性）
    const defaults = {
        // 基本属性
        url: '',            // 远程数据请求地址
        datatype: 'json',   // 数据格式
        mtype: 'POST',      // 请求方式 (GET/POST)

        // 表格列相关
        colNames: [],       // 列标题，可选，若 colModel 中未指定 label 或 name
        colModel: [],       // 列模型

        // 外观 & 行数分页
        height: 'auto',     // 表格高度，可指定具体数值
        width: 'auto',      // 表格宽度，可指定具体数值
        autowidth: true,    // 自动根据父容器调整宽度
        shrinkToFit: false,  // 宽度是否按比例缩放适应(用于控制列宽是否自适应整个表格宽度。设置为 false 时，每列的宽度会根据内容自动扩展，而不会强制压缩以适应表格的总宽度。)
        rowNum: 10,         // 每页默认显示行数
        rowList: [10, 20, 50, 100],
        viewrecords: true,  // 是否显示记录总数
        pager: '#jqGridPager', // 分页条
        pagerpos: 'center',  // 分页条位置 (center/left/right)
        sortname: '',       // 默认排序字段
        sortorder: '',      // 默认排序顺序 (asc/desc)

        // 行号、多选
        rownumbers: false,   // 是否显示行号
        rownumWidth: 25,     // 行号列宽度
        multiselect: true,   // 是否支持多选, 启用多选框
        multiselectWidth: 50,// 设置多选框列的宽度
        multiboxonly: true,  // 是否仅通过选择框来多选(即点击行本身不触发多选)

        // 其他外观增强
        altRows: false,        // 斑马纹
        altclass: 'ui-priority-secondary',
        caption: '',   // 表格标题

        // 数据交互
        postData: {},          // 提交到服务器的额外参数
        serializeGridData: null, // 自定义数据序列化函数
        loadonce: false,       // 是否只从服务器加载一次, 如果为 true，数据加载一次后分页功能完全在前端处理
        jsonReader: {//jsonReader 用于告诉 jqGrid 如何解析后端返回的数据结构。您目前的配置与常见后端分页数据结构相匹配。
            root: "extend.pageInfo.list",
            page: "extend.pageInfo.pageNum",
            total: "extend.pageInfo.pages",
            records: "extend.pageInfo.total",
            repeatitems: false                    // 数据是否用数组表示，false表示用对象
        },

        //分页
        pgtext: "第 {0} 页，共 {1} 页", // 自定义分页信息
        recordtext: "显示 {0} - {1} 条，共 {2} 条记录", // 自定义记录显示信息
        emptyrecords: "没有符合条件的数据", // 当没有数据时显示的提示

        // 子表格 (若有需要可打开)
        subGrid: false,
        subGridRowExpanded: null,
        subGridRowColapsed: null,
        subGridOptions: {},

        // 分组 (若有需要可打开)
        grouping: false,
        groupingView: {},

        // 合计行
        footerrow: true,    // 启用页脚功能
        userDataOnFooter: false,  // 是否将 userdata 显示到 footer

        // 模板
        cmTemplate: {},

        // 常见事件回调
        beforeRequest: null,
        loadComplete: null,
        loadError: null,
        beforeProcessing: null,
        gridComplete: null,
        onSelectRow: null,
        onSelectAll: null,
        onPaging: null,

        // 排序
        // prmNames: {},  // 可以设置发送到服务器的各种参数名称，如 'sort', 'order' 等
        prmNames: {
            page: "pageNum",     // 后端分页参数：当前页
            rows: "pageSize",    // 后端分页参数：每页记录数
            sort: "sort",        // 排序字段（如有需要）
            order: "order"       // 排序方式（如有需要）
        },

        // 这里还可以根据业务需要扩展更多 jqGrid 属性 ...
    };

    // 深度合并默认配置和用户自定义配置
    const finalOptions = $.extend(true, {}, defaults, config);

    // 初始化表格
    $("#jqGrid").jqGrid(finalOptions);

    // 设置分页导航条
    $("#jqGrid").jqGrid('navGrid', finalOptions.pager, {
        edit: false,
        add: false,
        del: false,
        search: false,
        refresh: true
        // 这里也可根据需求对导航条按钮进行启用或禁用
    });
}

/**
 * 重置查询条件，根据传入的配置自定义行为
 * @param {Object} options - 配置对象
 * @param {Array} [options.excludeIds=[]] - 需要保留不清空的输入框的ID数组
 * @param {Object} [options.setValues={}] - 需要设置值的输入框的ID和值的键值对
 * @param {Boolean} [options.reload=true] - 是否触发表格刷新
 */
function resetSearch(options = {}) {
    const {
        excludeIds = [],
        setValues = {},
        reload = true
    } = options;

    // 重置表单中的输入元素
    $('#searchForm').find('input, select, textarea').each(function () {
        const element = $(this);
        const elementId = element.attr('id');

        if (elementId && excludeIds.includes(elementId)) {
            return; // 跳过当前元素
        }

        if (element.hasClass('easyui-textbox')) {
            element.textbox('clear');
        } else if (element.hasClass('easyui-combobox')) {
            element.combobox('clear');
        } else if (element.hasClass('easyui-datebox')) {
            element.datebox('clear');
        }
    });

    // 设置指定输入框的值
    for (const [id, value] of Object.entries(setValues)) {
        const element = $('#' + id);
        if (element.length) {
            if (element.hasClass('easyui-textbox')) {
                element.textbox('setValue', value);
            } else if (element.hasClass('easyui-combobox')) {
                element.combobox('setValue', value);
            } else if (element.hasClass('easyui-datebox')) {
                element.datebox('setValue', value);
            } else {
                element.val(value);
            }
        }
    }

    // 根据需要触发表格刷新
    if (reload) {
        // 收集保留字段的当前值
        const queryParams = {};

        // 从 excludeIds 收集当前值
        excludeIds.forEach(id => {
            const element = $('#' + id);
            if (element.length) {
                let value;
                if (element.hasClass('easyui-textbox')) {
                    value = element.textbox('getValue');
                } else if (element.hasClass('easyui-combobox')) {
                    value = element.combobox('getValue');
                } else if (element.hasClass('easyui-datebox')) {
                    // 处理日期范围
                    const dateVal = element.datebox('getValue');
                    if (dateVal && dateVal.includes(' - ')) {
                        const dates = dateVal.split(' - ');
                        queryParams[id + 'Start'] = dates[0];
                        queryParams[id + 'End'] = dates[1];
                    } else {
                        queryParams[id] = dateVal;
                    }
                }
                if (value !== undefined && value !== null && value !== '') {
                    queryParams[id] = value;
                }
            }
        });

        // 合并 setValues，这些值会覆盖从 excludeIds 收集的值（如果有冲突）
        Object.assign(queryParams, setValues);

        // 重新加载数据表格，传递查询参数
        $('#datagrid').datagrid('load', queryParams);
    }
}

// 查询数据函数
function searchData(options = {}) {
    const {
        condition = false,   // condition标识是否必须要携带查询条件 标识符. 如果为false, 不对查询条件做检查; 如果为true, 检查查询条件.
        setValues = {}
    } = options;

    var hasCondition = false; // 标记是否有查询条件

    // 获取查询条件的值（表单序列化）
    var serialize = $('#searchForm').serialize().split('&');
    // console.log("serialize==========", serialize);
    // 将序列化的查询条件转成对象格式
    var queryParams = {};
    queryParams.params = typeof (queryParams.params) === 'object' && queryParams.params !== null && !Array.isArray(queryParams.params) ? queryParams.params : {};
    serialize.forEach(function (item) {
        var [key, value] = item.split('=');

        value = decodeURIComponent(value);
        // 检查是否为日期范围字段
        if (value.includes(' - ')) {
            // 分解日期范围
            var [startDate, endDate] = value.split(' - ');
            queryParams.params[key + 'Start'] = startDate;
            queryParams.params[key + 'End'] = endDate;
        } else if (value && value !== '') {
            // 普通字段直接添加, 筛选掉空值和空串
            queryParams[key] = value;
            hasCondition = true; // 存在有效条件
        }
    });

    // 如果没有条件则提示用户，并终止查询
    if (condition && !hasCondition) {
        alert('请至少填写一个查询条件！');
        return;
    }

    // 遍历对象, 设置指定的值
    for (const [key, value] of Object.entries(setValues)) {
        queryParams[key] = value;
    }

    console.log("queryParams====>", queryParams);


    // 重新加载表格数据，传递查询条件

    // load() 期望对象格式：datagrid('load', params) 中的 params 必须是一个 JavaScript 对象

    //load 方法
    //使用新的查询参数重新加载数据网格的内容。
    //可以传递查询参数，替换网格的当前查询参数。

    //当 reload 方法带参数时：
    // 它会 合并当前网格的已有查询参数 和 新传递的参数，然后重新加载数据。
    // 如果传递的参数中有与已有参数重名的键，则会覆盖已有参数。

    // 如果是 GET 请求，datagrid 会把对象转换为查询字符串（?rejectReason=xxx&createTime=2024-12-01）并将其附加到 URL 中。
    // 如果是 POST 请求，datagrid 会将这个对象作为请求体发送 rejectReason=&createTime=2024-12-04&pageNum=1&pageSize=10
    $('#datagrid').datagrid('reload', queryParams);
}

function formatDate(value, row, index) {
    if (!value) return ''; // 如果值为空，则返回空字符串

    // 如果 value 包含 "time" 字段，则直接使用它作为时间戳
    if (value.time) {
        return moment(value.time).format('YYYY-MM-DD HH:mm:ss');
    }

    if (value.year !== undefined && value.month !== undefined && value.date !== undefined) {
        // 手动构造一个 Date 对象
        const date = new Date(
            value.year + 1900, // 修正年份
            value.month,       // 修正月份，月份从 0 开始
            value.date,
            value.hours || 0,
            value.minutes || 0,
            value.seconds || 0
        );
        return moment(date).format('YYYY-MM-DD HH:mm:ss');
    }

    // 如果 value 是一个标准时间对象或字符串
    return moment(value).format('YYYY-MM-DD HH:mm:ss');
}

/**
 * 通用导出 Excel 函数
 * @param {string} actionName 后端处理 Excel 导出的接口
 * @param {string} tableId 数据表格的 ID
 * @param {string} searchFormId 搜索表单的 ID
 * @param {string} selectField 需要选中的字段名 (默认为 id)
 * @param {string} selectIdsParamName 提交时的参数名，对应后端实体类中的字段名
 */
function excelDoc(actionName,
                  {tableId = 'datagrid', searchFormId = 'searchForm', selectField = 'id',
                      selectIdsParamName = 'selectedIds', params = {}} = {}) {
    // 函数体
    console.log(`actionName: ${actionName}`);
    console.log(`tableId: ${tableId}`);
    console.log(`searchFormId: ${searchFormId}`);
    console.log(`selectField: ${selectField}`);
    console.log(`selectIdsParamName: ${selectIdsParamName}`);

    // 获取查询后的所有数据（可能跨页）
    var datas = $('#' + `${tableId}`).datagrid('getData').rows;
    if (datas.length == 0) {
        $.messager.alert('信息提示', '暂无数据!!!', 'info');
        return;
    }
    // 获取选中的行
    var rows = $('#' + `${tableId}`).datagrid('getSelections');
    console.log("rows===========>", rows);
    var ids = [];

    // 判断是否有选中项
    if (rows.length === 0) {
        // 如果没有选中条目，默认导出所有数据
        var ids = [];// 如果未选中任何数据，清空 selectIds 以便后端导出全部数据
    } else {
        // 如果选中条目，导出选中的数据
        var ids = rows.map(function(row) {
            return row[`${selectField}`]; // 动态获取指定字段的值
        });
    }
    console.log("ids===========>", ids);

    // 创建一个表单，提交到后端进行文件下载
    var form = $('<form method="POST"></form>');
    form.attr("action", `${actionName}`);

    // 将每个 ID 都作为一个独立的隐藏字段添加到表单中
    // 动态生成隐藏字段并附加到表单
    ids.forEach(function(id) {
        // 动态构造隐藏字段的 name 属性
        $('<input type="hidden" name="' + `${selectIdsParamName}` + '" value="' + id + '">').appendTo(form);
    });

    // 处理表单中的输入
    var formData = $('#' + `${searchFormId}`).serializeArray();
    // 遍历表单字段并添加到动态表单
    $.each(formData, function (i, field) {
        // 判断字段值是否为空，避免添加空值字段
        var value = field.value.trim();
        if (value) {
            // 创建隐藏字段并添加到表单
            $('<input>', {
                type: 'hidden',
                name: field.name,
                value: value
            }).appendTo(form);
        }
    });

    // 将表单添加到 body，然后提交表单
    form.appendTo('body');
    form.submit();
    // 提交后移除表单
    form.remove();
}

//在表单提交前，手动遍历表单字段，移除值为空的字段。
function removeEmptyFields(form) {
    $(form).find(':input').each(function() {
        if (!$(this).val()) {
            $(this).removeAttr('name');
        }
    });
}

// 格式化器：将 Date 对象转为 'yyyy-MM-dd HH:mm:ss' 格式的字符串
function formatter(date) {
    if (!date) return '';
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var d = date.getDate();
    var h = date.getHours();
    var minute = date.getMinutes();
    var second = date.getSeconds();
    return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' +
        (h < 10 ? '0' + h : h) + ':' + (minute < 10 ? '0' + minute : minute) + ':' +
        (second < 10 ? '0' + second : second);
}

// 解析器，将字符串转为 Date 对象
function parser(s) {
    if (!s) return new Date();

    if (typeof s === 'number') {
        // 如果是时间戳
        return new Date(s);
    }
    if (s instanceof Date) {
        // 如果是 Date 对象
        return s;
    }

    // 处理字符串格式 yyyy-MM-dd HH:mm:ss
    var parts = s.split(' ');
    var dateParts = parts[0].split('-');
    var timeParts = parts[1] ? parts[1].split(':') : [0, 0, 0];
    var y = parseInt(dateParts[0], 10);
    var m = parseInt(dateParts[1], 10) - 1;
    var d = parseInt(dateParts[2], 10);
    var h = parseInt(timeParts[0], 10);
    var min = parseInt(timeParts[1], 10);
    var sec = parseInt(timeParts[2], 10);
    if (!isNaN(y) && !isNaN(m) && !isNaN(d) && !isNaN(h) && !isNaN(min) && !isNaN(sec)) {
        return new Date(y, m, d, h, min, sec);
    } else {
        return new Date();
    }
}

/**
 * 格式化图片字段
 * @param {string} value - 图片的 URL 地址
 * @param {number} width - 图片宽度
 * @param {number} height - 图片高度
 * @param {string} altText - 图片的替代文本
 * @returns {string} HTML 字符串，用于展示图片
 */
function formatImage(value, row, index, width = 100, height = 100, altText = '图片') {
    // 普通行图片数据的格式化逻辑
    if (value) {
        //这里使用了 flexbox 布局，通过 justify-content: center 和 align-items: center 将图片水平垂直居中，同时移除了其他多余的样式。
        return `
            <div style="display: flex; justify-content: center; align-items: center; height: 100%; padding: 0;">
                 <a href="${value}" target="_blank" style="display: flex; justify-content: center; align-items: center;">
                    <img src="${value}" alt="${altText}" style="max-width: ${width}px; max-height: ${height}px; display: block;" />
                </a>
            </div>`;
    }
    return '无图片';
}

//封装通用 formatter 函数
function generalFormatter(value, row, index, mapping, defaultValue = '未知') {
    // 如果是 footer 数据，不做处理，直接返回原始值
    if (row && row.isFooter) {
        return value;
    }
    // 普通行数据的格式化逻辑
    return mapping[value] || defaultValue;
}


function initializeDateRangePickers(options = {}) {
    const {
        selector = '.daterange', // 选择器，默认为 '.daterange'
        editable = false,        // 是否允许手动输入
        required = false,        // 是否必填
        locale: customLocale = {}, // 用户传入的 locale 配置，赋给customLocale, 默认为空对象
        autoUpdateInput = false, // 不自动更新输入框
        opens = 'right',         // 日历弹出方向
        drops = 'down',          // 日历弹出位置
        singleDatePicker = false,// 是否单日期选择
        showDropdowns = false,   // 是否显示年份和月份下拉框
        alwaysShowCalendars = true // 始终显示日历
    } = options;

    // 默认的 locale 配置
    const defaultLocale = {
        format: 'YYYY-MM-DD',
        applyLabel: '确定',
        cancelLabel: '取消',
        daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
        monthNames: [
            '一月', '二月', '三月', '四月', '五月', '六月',
            '七月', '八月', '九月', '十月', '十一月', '十二月'
        ],
        firstDay: 1
    };

    // 合并默认 locale 和用户定制化的 locale
    const locale = { ...defaultLocale, ...customLocale };

    // 遍历所有匹配的输入框
    $(selector).each(function () {
        const $input = $(this);

        // 初始化 EasyUI Datebox
        $input.datebox({
            editable, // 是否允许手动输入
            required, // 是否必填
            formatter: function (date) {
                if (!date) return '';
                // 获取存储的结束日期
                const endDate = $input.data('endDate') || '';
                return moment(date).format(locale.format) + (endDate ? ' - ' + endDate : '');
            },
            parser: function (s) {
                if (!s) return null;
                // 仅解析起始日期
                const parts = s.split(' - ');
                return moment(parts[0], locale.format).toDate();
            },
            onShowPanel: function () {
                // 隐藏 EasyUI 自带的面板
                $input.datebox('hidePanel');

                const $textbox = $input.datebox('textbox');

                // 初始化 Daterangepicker
                if (!$textbox.data('daterangepicker')) {
                    $textbox.daterangepicker({
                        locale,
                        autoUpdateInput,
                        opens,
                        drops,
                        singleDatePicker,
                        showDropdowns,
                        alwaysShowCalendars
                    }, function (start, end) {
                        // 更新 Datebox 的值
                        const startDate = start.format(locale.format);
                        const endDate = end.format(locale.format);

                        // 存储结束日期
                        $input.data('endDate', endDate);
                        $input.datebox('setValue', startDate + ' - ' + endDate);
                    });

                    // 处理取消按钮事件
                    $textbox.on('cancel.daterangepicker', function () {
                        $input.datebox('clear');
                        $input.data('endDate', '');
                    });
                }
            }
        });
    });
}




/**
 * 智能表格尺寸自适应控制器
 * @param {string} gridSelector - 表格选择器 (#jqGrid)
 * @param {string} parentSelector - 父容器选择器 (.container)
 * @param {Object} [options] - 配置选项
 * @param {number} [options.widthOffset=2] - 宽度补偿值
 * @param {Object} [options.breakpoints] - 响应式断点配置
 * @param {boolean} [options.debug=false] - 调试模式
 */
function initializeGridResize(gridSelector, parentSelector, options = {}) {
    // 参数合并与默认配置
    const DEFAULTS = {
        widthOffset: 2,
        breakpoints: { desktop: 1200, tablet: 768, mobile: 480 },
        debug: false
    };
    const config = { ...DEFAULTS, ...options };

    // 元素缓存
    const $grid = $(gridSelector);
    const $parent = $(parentSelector);
    const $window = $(window);

    // 防御性检查
    if ($grid.length  * $parent.length  === 0) {
        config.debug  && console.error('[GridResize]  元素未找到');
        return;
    }

    // 销毁旧实例
    if ($grid.data('jqGrid'))  {
        $grid.jqGrid('GridUnload');
        $window.off('.gridResize');
    }

    // 防抖处理器
    const debounce = (fn, delay) => {
        let timer;
        return (...args) => {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this,  args), delay);
        };
    };

    // 核心尺寸计算
    const calculateDimensions = () => {
        // 动态宽度计算
        const containerWidth = $parent.innerWidth()  - config.widthOffset;
        $grid.jqGrid('setGridWidth',  containerWidth);

        // 响应式列宽调整
        if (containerWidth >= config.breakpoints.desktop)  {
            $grid.jqGrid('setColWidth',  'boxId', 150);
        } else if (containerWidth >= config.breakpoints.tablet)  {
            $grid.jqGrid('setColWidth',  'boxId', 120);
        } else {
            $grid.jqGrid('setColWidth',  'boxId', 100);
        }

        // 动态高度计算
        const headerHeight = $('.page-header').outerHeight() || 0;
        const availableHeight = $window.height()  - headerHeight - 30;
        $grid.jqGrid('setGridHeight',  availableHeight);
    };

    // 事件绑定
    const handleResize = debounce(() => {
        calculateDimensions();
        config.debug  && console.log('[GridResize]  尺寸已更新');
    }, 300);

    // 初始化执行
    calculateDimensions();
    $window.on('resize.gridResize  orientationchange.gridResize',  handleResize);

    // 侧边栏折叠监听
    $(document).on('sidebarCollapse.gridResize',  () => {
        setTimeout(calculateDimensions, 200);
    });

    // 过渡动画支持
    $grid.addClass('grid-transition');
}
